package org.jheuristics.ga.operators;

import java.io.Serializable;

import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;

/**
 * TODO
 *
 * @author Marcell Manfrin, marcell@ourgrid.org, Dec 13, 2005
 */
public class SelectionOperator extends AbstractSelectionOperator implements Serializable {
	private PopulationChooser fromPopChooser;
	private PopulationChooser toPopChooser;
	private ClosureSelection afterSelectionClosure;
	private ClosureSelection beforeInsertionClosure;

	/**
	 * TODO
	 *
	 * @param rate
	 * @param selector
	 * @param fromPopChooser
	 * @param toPopChooser
	 */
	public SelectionOperator(Rate rate, Selector selector, PopulationChooser fromPopChooser, PopulationChooser toPopChooser) {
		super(rate, selector);
		if (null == fromPopChooser) {
			// TODO: ERROR MSG
			throw new NullPointerException();
		}
		if (null == toPopChooser) {
			// TODO: ERROR MSG
			throw new NullPointerException();
		}
		this.fromPopChooser = fromPopChooser;
		this.toPopChooser = toPopChooser;
		this.afterSelectionClosure = null;
		this.beforeInsertionClosure = null;
	}

	/**
	 * TODO
	 *
	 * @param rate
	 * @param selector
	 * @param fromPopChooser
	 * @param cleanAfterFromPop
	 * @param toPopChooser
	 * @param cleanBeforeToPop
	 */
	public SelectionOperator(Rate rate, Selector selector, PopulationChooser fromPopChooser, ClosureSelection afterSelectionClosure, PopulationChooser toPopChooser, ClosureSelection beforeInsertionClosure) {
		this(rate, selector, fromPopChooser, toPopChooser);
		this.afterSelectionClosure = afterSelectionClosure;
		this.beforeInsertionClosure = beforeInsertionClosure;
	}

	/**
	 * TODO
	 *
	 * @param status
	 * @param config
	 * @see org.jheuristics.ga.Operator#operate(org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	public void operate(GAStatus status, GAConfig config) {
		Population fromPop = fromPopChooser.choose(status, config);
		Population toPop = toPopChooser.choose(status, config);
		Population selectedIndividuals = select(fromPop, status, config);
		
//		SPLogger.getInstancia().log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, "getSelector() "+getSelector());
//		SPLogger.getInstancia().log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, "fromPopChooser "+fromPopChooser);
//		SPLogger.getInstancia().log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, "toPopChooser "+toPopChooser);
//		SPLogger.getInstancia().log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, "fromPop "+fromPop.size());
//		SPLogger.getInstancia().log(SPLogger.OTIMIZACAO, SPLogger.DEBUG, "toPop "+toPop.size());
		
		if (null != afterSelectionClosure) {
			afterSelectionClosure.execute(selectedIndividuals, fromPop, status, config);
		}
		if (null != beforeInsertionClosure) {
			beforeInsertionClosure.execute(selectedIndividuals, toPop, status, config);
		}
		
		toPop.addIndividuals(selectedIndividuals);
		
	}

	/**
	 * TODO
	 *
	 * @return
	 */
	public ClosureSelection getAfterSelectionClosure() {
		return afterSelectionClosure;
	}

	/**
	 * TODO
	 *
	 * @param afterSelectionClosure
	 */
	public void setAfterSelectionClosure(ClosureSelection afterSelectionClosure) {
		this.afterSelectionClosure = afterSelectionClosure;
	}

	/**
	 * TODO
	 *
	 * @return
	 */
	public ClosureSelection getBeforeInsertionClosure() {
		return beforeInsertionClosure;
	}

	/**
	 * TODO
	 *
	 * @param beforeInsertionClosure
	 */
	public void setBeforeInsertionClosure(ClosureSelection beforeInsertionClosure) {
		this.beforeInsertionClosure = beforeInsertionClosure;
	}

}
